#include "directoryDB.h"
extern mr_log_p MHD_log;

extern mr_conf_p pconf;


dbstr_p nextdbstr(dbstr_p pstr) {
	return (dbstr_p)(((char *)pstr) + pstr->len + sizeof(pstr->len));
}

void directory_free(void * arg){
	directory_p pdir = (directory_p)arg;

	if( !pdir )
		return;
	if(pdir->password)
		free(pdir->password);
	if(pdir->context)
		free(pdir->context);
	if(pdir->group)
		free(pdir->group);
	if(pdir->owner)
		free(pdir->owner);
	if(pdir->domain)
		free(pdir->domain);
	free(pdir);
}

/*********************************************************************/
/* Build DBT object from link structure.
   Html <tags> is converted to [tags], '\n' is converted to ' '
   Space for .data is allocated, this field must be freed after use!
   If error occures val.data is set to NULL! */
DBT directory2dbt(directory_p  link){

	DBT val = mk_empty_dbt();
	//int ptr;
	directory_p  obj;
	dbstr_p		pstr;

/*	printf("/---directory2dbt---\\\n");
	printf("num = %d\n", link->num);
	printf("password = '%s'\n", link->password);
	printf("group = '%s'\n", link->group);
	printf("domain = '%s'\n", link->domain);
	printf("context = '%s'\n", link->context);
	printf("owner = '%s'\n", link->owner);
	printf("\\---directory2dbt---/\n");*/

  /* calculate data size and build data structure */
	val.size =
		//sizeof(directory_t)   /* static fields + pointers */
		 strlen(link->password) + 1 /* including \0*/
		+ strlen(link->group) + 1
		+ strlen(link->domain) + 1
		+ strlen(link->context) + 1
		+ strlen(link->owner) + 1
		+ sizeof(int);
	val.data = malloc(val.size);
	if (val.data==NULL){
		mr_logger_write(MHD_log,LL_ERROR,"Directory2dbt: Can't allocate Memory \n");
		return val;
	}

	/* copy link to the header of val.data */
	obj = (directory_p)val.data;
	//*obj = *link;
	obj->num = link->num;

	pstr = (dbstr_p)(((char *)val.data) + sizeof(int));
	pstr->len = strlen(link->password);
	memcpy(pstr->str, link->password, pstr->len);

	pstr = nextdbstr(pstr);
	pstr->len = strlen(link->group);
	memcpy(pstr->str, link->group, pstr->len);

	pstr = nextdbstr(pstr);
	pstr->len = strlen(link->domain);
	memcpy(pstr->str, link->domain, pstr->len);

	pstr = nextdbstr(pstr);
	pstr->len = strlen(link->context);
	memcpy(pstr->str, link->context, pstr->len);

	pstr = nextdbstr(pstr);
	pstr->len = strlen(link->owner);
	memcpy(pstr->str, link->owner, pstr->len);

	return val;
}

char * dbstr2str(dbstr_p *pstr) {
	char	*	p;
	dbstr_p		mystr = *pstr;

	p = malloc(mystr->len + 1);
	memcpy(p, mystr->str, mystr->len);
	p[mystr->len] = '\0';

	*pstr = (dbstr_p)(((char *)mystr) + mystr->len + sizeof(mystr->len));

	return p;
}

/* Convert DBT structure to event. Data is not copied! */
directory_p  dbt2directory(const DBT * dbt){
	dbstr_p		pstr;
	directory_p pdirectory;
	pdirectory =(directory_p) malloc (sizeof(directory_t));
	memset(pdirectory,0 ,sizeof(directory_t));

	pdirectory->num = *(int *)dbt->data;

	//ev.num = *(int *)dbt->data;
	pstr = dbt->data + sizeof(int);
		
	pdirectory->password = dbstr2str(&pstr);
	pdirectory->group = dbstr2str(&pstr);
	pdirectory->domain = dbstr2str(&pstr);
	pdirectory->context = dbstr2str(&pstr);
	pdirectory->owner = dbstr2str(&pstr);

/*	ev.password = dbstr2str(&pstr);
	ev.group = dbstr2str(&pstr);
	ev.domain = dbstr2str(&pstr);
	ev.context = dbstr2str(&pstr);
	ev.owner = dbstr2str(&pstr);*/

	/*printf("/---dbt2directory---\\\n");
	printf("num = %d\n", pdirectory->num);
	printf("password = '%s'\n", pdirectory->password);
	printf("group = '%s'\n", pdirectory->group);
	printf("domain = '%s'\n",pdirectory->domain);
	printf("context = '%s'\n", pdirectory->context);
	printf("owner = '%s'\n", pdirectory->owner);
	printf("\\---dbt2directory---/\n");
*/
	return pdirectory;
}

int db_name_extentionid (DB *secdb, const DBT *pkey, const DBT *pdata, DBT *skey){

	static char * val;
	directory_p mdirectory = dbt2directory(pdata);
	memset(skey, 0, sizeof(DBT));
	val= mdirectory->owner;
	skey->data = val;
	skey->size = strlen(val)+1;
	return 0;
}
int directory_put(unsigned int id, directory_p *obj, int flags){
	
	DBT key = mk_uint_dbt(&id);
	DBT val = directory2dbt(*obj); /* do free before return! */
	int ret;
	
	if (val.data==NULL) return -1;
	/* write link */
	ret = dbs.extention->put(dbs.extention, NULL, &key, &val, flags);
	if (ret!=0)
		mr_logger_write(MHD_log,LL_ERROR,"%s\n",db_strerror(ret));

	free(val.data);
	return ret;
}

int directory_create(struct MHD_Connection *connection,app_con_info_p sysdata, int uri_num){
	
	json_t *root , *response;
	json_error_t error;
	directory_p obj;   
	obj = (directory_p)malloc(sizeof(directory_t));
	memset(obj,0,sizeof(directory_t));
	int extention;
	char *responsestr ,*password,*context,*domain,*group,*owner;
         
	mr_logger_write(MHD_log,LL_TRACE,"create_a_directory\n");
        mr_logger_write(MHD_log,LL_TRACE,"url : %s\n",sysdata->url);
        mr_logger_write(MHD_log,LL_TRACE,"method : %s\n",sysdata->method);
        mr_logger_write(MHD_log,LL_TRACE,"post_data : %s\n",sysdata->post_data);
        mr_logger_write(MHD_log,LL_TRACE,"request_mime_type : %s\n",sysdata->request_mime_type);
       
        if(sysdata->post_data){
                root = json_loads(sysdata->post_data,0,&error);
		/* rv=  json_unpack(root, "{s:i, s:s ,s:s,s:s,s:s,s:s}",
                            "extention", &extention,
                            "password", &password ,
                            "context", &context ,
                            "domain", &domain ,
                            "group", &group ,
                            "owner" , &owner);*/
              if(json_unpack_ex(root,
                                &error,
                                0,
                                "{s:i, s:s, s:s, s:s, s:s, s:s}",
                                "extention", &extention,
                                "password", &password ,
                                "context", &context ,
                                "domain", &domain ,
                                "group", &group ,
                                "owner" , &owner) < 0)
              {
                  response = json_pack("{s:{s:b,s:s ,s:i}}",
                                                              "metadata",
                                                               "success" ,0,
                                                              "description" ,error.text,
                                                              "lineNumber" ,error.line

                                                              );


                                         responsestr =json_dumps(response,0);
                                         mr_logger_write(MHD_log,LL_ERROR,responsestr);
                                         json_decref(response);
                                         return response_write(connection,"application/json",MHD_HTTP_INTERNAL_SERVER_ERROR,responsestr);
              }


                }
		
	//	obj.num =atoi(extention_text);
	printf("************  password = '%s'\n", password);
	 obj->num = extention;
        obj->password=password;
        obj->group=group;
        obj->domain=domain;
        obj->context=context;
        obj->owner=owner;
                
		/* write metadata */
		//int ret =  directory_put(obj->num, &obj, DB_NOOVERWRITE);
//		DB_OVERWRITE
		int ret =  directory_put(obj->num, &obj, 0);
		json_decref(root);
		free(obj);
	if (ret!=0)
	{ 
		if(ret==DB_KEYEXIST){
		
                        return response_write(connection,"application/json",
					MHD_HTTP_INTERNAL_SERVER_ERROR,
					"{ \"error\" : \"DB_KEYEXIST: Key/data pair already exists\" } \n"
					);
		}else
		{
                        return response_write(connection,"application/json",
					MHD_HTTP_INTERNAL_SERVER_ERROR,
					"error :putting value to db\n"
					);
		}
					
	}
                return response_write(connection," application/json; charset=utf-8",
				MHD_HTTP_OK,"{\"result\" : \"Success\"} \n");


}

int directory_db_get(unsigned  int id,directory_p *obj){

	DBT key = mk_uint_dbt(&id);
	DBT val = mk_empty_dbt();
	val.flags = DB_DBT_MALLOC;
	int ret = dbs.extention->get(dbs.extention, NULL, &key, &val, 0);
	
	if (ret==DB_NOTFOUND){
		mr_logger_write(MHD_log,LL_ERROR,"Directory Not Found %d\n",id);
		return ret;
	}

	if (ret!=0){
		mr_logger_write(MHD_log,LL_ERROR,"DB Error :%s\n",db_strerror(ret));
		return ret;
	}

	*obj = dbt2directory(&val);
	free(val.data);
        return (0);
}


int directory_get(struct MHD_Connection *connection,app_con_info_p sysdata, int uri_num){
	
	int ret ;
	directory_p my_extention=NULL;
	json_t *root , *response;
	json_error_t error;
	int extention;
	char *responsestr ;
	
//	my_extention = (directory_p) malloc(sizeof(directory_t));
//	memset(my_extention,0,sizeof(directory_t));
	mr_logger_write(MHD_log,LL_TRACE,"directory_get\n");
	mr_logger_write(MHD_log,LL_TRACE,"url : %s\n",sysdata->url);

        if(sysdata->post_data){
                root = json_loads(sysdata->post_data,0,&error);
                if(!root)
                {       response = json_pack("{s:{s:b,s:s ,s:i}}",
                                             "metadata",
                                              "success" ,0,
                                             "description" ,error.text,
                                             "lineNumber" ,error.line
                                             );

                        responsestr =json_dumps(response,0);
                        mr_logger_write(MHD_log,LL_ERROR,responsestr);
                        json_decref(response);
                        return response_write(connection,"application/json",MHD_HTTP_INTERNAL_SERVER_ERROR,responsestr);
                }

              if(json_unpack_ex(root,
                                &error,
                                0,
                                "{s:i}",
                                "extention", &extention//,
                              //  "password", &password ,
                               // "context", &context ,
                               // "domain", &domain ,
                               // "group", &group ,
                               /* "owner" , &owner*/) < 0)
              {
                  response = json_pack("{s:{s:b,s:s ,s:i}}",
                                                              "metadata",
                                                               "success" ,0,
                                                              "description" ,error.text,
                                                              "lineNumber" ,error.line

                                                              );


                                         responsestr =json_dumps(response,0);
                                         mr_logger_write(MHD_log,LL_ERROR,responsestr);
                                         json_decref(response);
                                         return response_write(connection,"application/json",MHD_HTTP_INTERNAL_SERVER_ERROR,responsestr);
              }
        }
	json_decref(root);	
	ret =directory_db_get(extention,&my_extention);
	if(ret){
                             return  response_write(connection,"application/json",
					     MHD_HTTP_INTERNAL_SERVER_ERROR,
					     "{\"error\": \"not in db\" } \n");
	
	}else{
                             ret = response_write(connection,"application/json",
					     MHD_HTTP_OK,
					     "{\"extention\" : %d ,\"password\" :\"%s\",\"domain\" :\"%s\",\"context\" :\"%s\",\"owner\" :\"%s\" ,\"group\" : \"%s\"}\n",
					     my_extention->num,
					     my_extention->password,
					     my_extention->domain,
					     my_extention->context,
					     my_extention->owner,
					     my_extention->group
					     );
			     directory_free(my_extention);
			     return ret;

	}
	return  response_write(connection,"text/html",
		      MHD_HTTP_INTERNAL_SERVER_ERROR," directory get by id\n");



}


int directory_db_list(mr_list_p   pplist){
 
	DBT key = mk_empty_dbt();
	DBT val = mk_empty_dbt();
	directory_p obj;	
	val.flags = DB_DBT_MALLOC;
	DBC *cursorp;	
	int flag = DB_FIRST;
	int ret = dbs.extention->cursor(dbs.extention, NULL, &cursorp, 0);
	// iterate over the database , retrieving each record in turb  .
	while((ret=cursorp->get(cursorp,&key,&val,flag))==0){
		flag = DB_NEXT;
		obj = dbt2directory(&val);
		mr_list_push(pplist,obj, 0);
	}
	if (ret==DB_NOTFOUND){
		mr_logger_write(MHD_log,LL_ERROR,"Directory Not Found\n");
		return ret;
	}
	free(val.data);

	if(cursorp!=NULL)
	{
		cursorp->close(cursorp);
	}
        return (0);
}

int directory_list(struct MHD_Connection *connection,app_con_info_p sysdata, int uri_num){
	
	int ret ;
	mr_list_p plist;
	mr_list_init(&plist, directory_free);
	mr_listnode_p pnode =NULL;
	directory_p  pdata=NULL;
	char * response;
	ret=directory_db_list(plist);
	json_t *array;
	array =json_array();
	while( !mr_list_get_next(plist,&pnode, (void **)&pdata ) ) {
                 json_t *itemjson; 
		 itemjson=json_pack("{s:{s:i,s:s ,s:s,s:s,s:s,s:s}}",
                                                              "directory",
                                                               "extention" ,pdata->num,
                                                              "password" ,pdata->password,
                                                              "context" ,pdata->context ,
                                                              "domain" ,pdata->domain ,
                                                              "group" ,pdata->group ,
                                                              "owner" ,pdata->owner 
                                                             );
		printf("%s\n",json_dumps(itemjson,0));
		 json_array_append(array,itemjson);
		}
	       response =json_dumps(array,0);
               json_decref(array);
              ret= response_write(connection,"application/json",MHD_HTTP_OK,response);
	mr_list_destroy(plist);

	return ret;
}

